package com.pig4cloud.pig.ads.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.pig4cloud.pig.admin.api.entity.SysUser;
import com.pig4cloud.pig.admin.api.feign.RemoteUserService;
import com.pig4cloud.pig.ads.clickhouse3399.mapper.AdVideoOperateReportMapper;
import com.pig4cloud.pig.ads.clickhouse3399.mapper.AdVideoReportMapper;
import com.pig4cloud.pig.ads.gdt.service.GdtAccesstokenService;
import com.pig4cloud.pig.ads.pig.mapper.AdVideoMapper;
import com.pig4cloud.pig.ads.pig.mapper.AdVideoPlatformMapper;
import com.pig4cloud.pig.ads.service.*;
import com.pig4cloud.pig.ads.utils.DateUtils;
import com.pig4cloud.pig.ads.utils.OEHttpUtils;
import com.pig4cloud.pig.api.dto.AdVideoAdsReportDTO;
import com.pig4cloud.pig.api.dto.AdVideoOperateData;
import com.pig4cloud.pig.api.dto.AdVideoReport;
import com.pig4cloud.pig.api.dto.AdVideoReportData;
import com.pig4cloud.pig.api.entity.*;
import com.pig4cloud.pig.api.util.MapUtils;
import com.pig4cloud.pig.api.util.UploadUtils;
import com.pig4cloud.pig.api.vo.AdVideoPlatformVo;
import com.pig4cloud.pig.api.vo.AdVideoReportVo;
import com.pig4cloud.pig.api.vo.AdVideoSortVo;
import com.pig4cloud.pig.api.vo.AdVideoVo;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.constant.enums.PlatformTypeEnum;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.URI;
import java.util.*;

/**
 * @author cx
 * @version 1.0.0
 * @ClassName AdVideoServiceImpl.java
 * @createTime 2020年11月05日 14:02:00
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class AdVideoServiceImpl extends ServiceImpl<AdVideoMapper, AdVideo> implements AdVideoService {

	private final AdVideoMapper mapper;

	private final AdVideoPlatformService adVideoPlatformService;

	private final AdVideoPlatformMapper adVideoPlatformMapper;

	private final TtAccesstokenService ttAccesstokenService;

	private final AdVideoReportMapper adVideoReportMapper;

	private final PictureService pictureService;

	private final GdtAccesstokenService gdtAccesstokenService;

	private final AdVideoOperateReportMapper adVideoOperateReportMapper;

	private final AdvCreativeService advCreativeService;

//	private final AdVideoAdsReportMapper adVideoAdsReportMapper;

	private final RemoteUserService remoteUserService;

	@Autowired
	private AdvService advService;
	/**
	 * 上传地址
	 */
	@Value("${video_download_url}")
	private String downloadUrl;
	/**
	 * 下载地址
	 */
	@Value("${video_upload_path}")
	private String uploadPath;
	/**
	 * 限制大小
	 */
	@Value("${video_size}")
	private String size;
	/**
	 * 请求地址
	 */
	private String openApiUrlToutiao = "https://ad.oceanengine.com/open_api/2/file/video/ad/";
	/**
	 * 广点通接口地址前缀
	 */
	@Value(value = "${gdt_url}")
	private String gdtUrl;
	@Value(value = "${gdt_video_add}")
	private String gdtVideoAdd;

	@Value(value = "${pig_schema}")
	private String pigSchema;

	@Value(value = "${ch_3399_schema}")
	private String ch3399Schema;



	/**
	 * 视频列表分页
	 * @param req
	 * @return
	 */
	@Override
	public IPage<AdVideoVo> selectAdVideoListPage(AdVideoVo req){
		List<String> adList = Lists.newArrayList();
		//[头条]当前用户绑定的广告账户
		List<String> ttAdList = advService.getOwnerAdv(SecurityUtils.getUser().getId(), PlatformTypeEnum.TT.getValue());
		req.setTtAdList(ttAdList);
		adList.addAll(ttAdList);
		//[广点通]当前用户绑定的广告账户
		List<String> gdtAdList = advService.getOwnerAdv(SecurityUtils.getUser().getId(), PlatformTypeEnum.GDT.getValue());
		req.setGdtAdList(gdtAdList);
		adList.addAll(gdtAdList);
		//查询分页数据
		req.setAdList(adList);
		req.setCreateuser(String.valueOf(SecurityUtils.getUser().getId()));
		if(org.apache.commons.lang3.StringUtils.isNotEmpty(req.getLabelname())){
			req.setLabelname("%"+req.getLabelname()+"%");
		}
		IPage<AdVideoVo> page = mapper.selectAdVideoListPage(req);
		//处理列表数据
		dealVideoData(page,ttAdList,gdtAdList);
		return page;
	}


	/**
	 * 视频列表分页
	 * @param req
	 * @return
	 */
	@Override
	public List<AdVideoAdsReportDTO> selectAdVideoSortList(AdVideoSortVo req){
		Long startTime = req.getStartTime();
		Long endTime = req.getEndTime();
		Date now = new Date();
		if(startTime == null){
			req.setStartTime(Long.valueOf(DateUtils.dateToString(now, -7, DateUtils.YYYYMMDD)));
		}
		if(endTime == null){
			req.setEndTime(Long.valueOf(DateUtils.dateToString(now, DateUtils.YYYYMMDD)));
		}
		Map<String, Object> params = JSONObject.parseObject(JSON.toJSONString(req), new TypeReference<Map<String, Object>>(){});
		//增加presto动态schema
		params.put("pigSchema", pigSchema);
		params.put("ch3399Schema", ch3399Schema);
		return new ArrayList<>();//adVideoAdsReportMapper.selectAdVideoAdsReportForCreative(params);
	}




	public void dealVideoData(IPage<AdVideoVo> page,List<String> ttAdList,List<String> gdtAdList){
		if (null != page && page.getRecords().size() > 0){
			int ttAdSum = ttAdList.size();
			int gdtAdSum = gdtAdList.size();
			List<AdVideoVo> adVideoList = page.getRecords();
			for (AdVideoVo adVideoVo:adVideoList){
				//[头条]同步状态
				if (StringUtils.isNotBlank(adVideoVo.getTtSynAds())){
					String[] ttSynAds = adVideoVo.getTtSynAds().split(",");
					if (ttSynAds.length < ttAdSum){
						adVideoVo.setTtSyn(1); //部分同步
					}else if (ttSynAds.length == ttAdSum){
						adVideoVo.setTtSyn(2); //全部同步
					}
				}else{
					adVideoVo.setTtSyn(0); //未同步
				}
				//[广点通]同步状态
				if (StringUtils.isNotBlank(adVideoVo.getGdtSynAds())){
					String[] gdtSynAds = adVideoVo.getGdtSynAds().split(",");
					if (gdtSynAds.length < gdtAdSum){
						adVideoVo.setGdtSyn(1); //部分同步
					}else if (gdtSynAds.length == gdtAdSum){
						adVideoVo.setGdtSyn(2); //全部同步
					}
				}else{
					adVideoVo.setGdtSyn(0); //未同步
				}
				//[头条]鼠标悬浮显示推送信息
				List<Map<String,Object>> ttAdStatusList = Lists.newArrayList();
				for (String ttAd : ttAdList){
					Map<String,Object> map = new HashMap<>();
					map.put("advertiserId",ttAd);
					map.put("pushStatus",0);
					if (StringUtils.isNotBlank(adVideoVo.getTtSynAds())){
						String[] ttSynAds = adVideoVo.getTtSynAds().split(",");
						for (String ttSynAd : ttSynAds){
							if (ttSynAd.equals(ttAd)){
								map.put("pushStatus",1);
							}
						}
					}
					ttAdStatusList.add(map);
				}
				adVideoVo.setPushTtAdStatusList(ttAdStatusList);
				//[广点通]鼠标悬浮显示推送信息
				List<Map<String,Object>> gdtAdStatusList = Lists.newArrayList();
				for (String gdtAd : gdtAdList){
					Map<String,Object> map = new HashMap<>();
					map.put("advertiserId",gdtAd);
					map.put("pushStatus",0);
					if (StringUtils.isNotBlank(adVideoVo.getGdtSynAds())){
						String[] gdtSynAds = adVideoVo.getGdtSynAds().split(",");
						for (String gdtSynAd : gdtSynAds){
							if (gdtSynAd.equals(gdtAd)){
								map.put("pushStatus",1);
							}
						}
					}
					gdtAdStatusList.add(map);
				}
				adVideoVo.setPushGdtAdStatusList(gdtAdStatusList);
			}
		}

	}

	/**
	 * 视频上传保存
	 * @param file
	 * @return
	 */
	@Override
	public R uploadVideo(MultipartFile[] file){
		String ymPath = DateUtils.dateToString(new Date(),DateUtils.YYYYMM) + "/";
		String upPath = uploadPath + ymPath;
		String downUrl = downloadUrl + ymPath;
		String vSize = size;
		try {
			if (null != file && file.length > 0) {
				List<AdVideo> adVideoList = Lists.newArrayList();
				List<AdVideo> repeatVideoList = Lists.newArrayList();
				String msg = "";
				AdVideo adVideo = new AdVideo();
				adVideo.setIsdelete(0);
				adVideo.setCreatetime(new Date());
				adVideo.setUpdatetime(new Date());
				adVideo.setCreateuser(String.valueOf(SecurityUtils.getUser().getId()));
				for (int i = 0; i < file.length; i++) {
					MultipartFile mFile = file[i];
					//查看视频是否已经上传
					String md5 = DigestUtils.md5Hex(mFile.getInputStream());
					AdVideo adv = mapper.selectOne(Wrappers.<AdVideo>query().lambda().eq(AdVideo::getMd5,md5).isNotNull(AdVideo::getFileUrl).last("LIMIT 1"));
					//如果视频已经存在，只做记录，不做上传操作
					if (null != adv){
						msg += "["+mFile.getOriginalFilename()+"]";
						repeatVideoList.add(adv);
					}else{
						Map<String, Object> resultMap = UploadUtils.videoUpload(mFile, upPath, Long.parseLong(vSize));
						if (null != resultMap && 0 == Integer.parseInt(String.valueOf(resultMap.get("code")))){
							if (null == resultMap.get("videoImgList")){
								log.error("截取视频封面异常");
								return R.failed("截取视频封面异常");
							}
							List<Map<String,Object>> videoImgList = (List<Map<String,Object>>) resultMap.get("videoImgList");
							adVideo.setVName(mFile.getOriginalFilename());//视频名称
							adVideo.setFileName(String.valueOf(resultMap.get("filename")));//文件名称
							adVideo.setFileUrl(downUrl + resultMap.get("filename"));//视频访问url
							adVideo.setImageUrl(downUrl + videoImgList.get(0).get("imageName"));//图片访问url
							adVideo.setWidth(String.valueOf(resultMap.get("width")));//视频宽
							adVideo.setHeight(String.valueOf(resultMap.get("height")));//视频高
							adVideo.setVSize(String.valueOf(resultMap.get("size")));//视频大小
							adVideo.setFormat(String.valueOf(resultMap.get("format")));//视频格式
							adVideo.setDuration(String.valueOf(resultMap.get("duration")));//视频时长
							adVideo.setRealPath(String.valueOf(resultMap.get("realPath")));//真实路径
							adVideo.setMd5(md5);//视频md5值
							adVideo.setScreenType(Integer.parseInt(resultMap.get("screenType").toString()));
							int num = mapper.insert(adVideo);
							if (num > 0) {
								adVideoList.add(adVideo);
								//保存视频图片
								saveVideoImg(videoImgList,adVideo,upPath,downUrl);
								log.info(adVideo.getVName()+"上传成功");
							} else {
								return R.failed(null,adVideo.getVName()+"上传失败");
							}
						}else {
							if (Objects.isNull(resultMap)){
								return R.failed(null,"操作失败");
							}else{
								log.error(String.valueOf(resultMap.get("msg")));
								return R.failed(null,String.valueOf(resultMap.get("msg")));
							}
						}
					}
				}
				if (repeatVideoList.size() > 0){
					log.error("视频"+msg+"已经上传，推送后即可查看");
					return R.failed(repeatVideoList,100,"视频"+msg+"已经上传，推送后即可查看");
				}else{
					return R.ok(adVideoList,"上传成功");
				}
			} else {
				log.error("未获取到视频文件");
				return R.failed("未获取到视频文件");
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error("文件上传失败：{}", e.getMessage());
			return R.failed(null,"文件上传失败");
		}
	}

	/**
	 * 视频封面图批量插入图片库
	 * @param videoImgList
	 * @param adVideo
	 * @param upPath
	 * @param downUrl
	 * @return
	 */
	public R saveVideoImg(List<Map<String,Object>> videoImgList,AdVideo adVideo,String upPath,String downUrl){
		if (videoImgList.size() > 0){
			List<PictureLib> plList = Lists.newArrayList();
			for (Map<String,Object> map : videoImgList ) {
				String md5 = DigestUtils.md5Hex(upPath + map.get("imageName"));
				PictureLib pictureLib = new PictureLib();
				pictureLib.setPictureName(adVideo.getVName()+"_进度"+map.get("videoRate")+"%封面图.jpg");
				pictureLib.setPictureFilename(String.valueOf(map.get("imageName")));
				pictureLib.setSourceType(2);
				pictureLib.setVideoId(Integer.parseInt(String.valueOf(adVideo.getId())));
				pictureLib.setPictureUrl(downUrl + map.get("imageName"));
				pictureLib.setRealPath(upPath + map.get("imageName"));
				pictureLib.setMd5(md5);
				pictureLib.setWidth(adVideo.getWidth());
				pictureLib.setHeight(adVideo.getHeight());
				pictureLib.setScreenType(adVideo.getScreenType());
				pictureLib.setFormat("jpg");
				pictureLib.setPictureSize(adVideo.getWidth()+"*"+adVideo.getHeight());
				pictureLib.setPictureStatus("1");
				pictureLib.setCreator(String.valueOf(SecurityUtils.getUser().getId()));
				pictureLib.setCreateTime(new Date());
				pictureLib.setUpdateTime(new Date());
				//设置图片类型
				pictureLib.setPictureType(AdPicturePlatformServiceImpl.getPicType(adVideo.getWidth(),adVideo.getHeight()));
				plList.add(pictureLib);
			}
			pictureService.saveBatch(plList);
		}
		return R.ok();
	}
	/**
	 * 推送视频
	 * @param req
	 * @return
	 */
	@Override
	public R<Map<String,Object>> pushVideo(AdVideoVo req){
		if (StringUtils.isBlank(req.getIds())){
			return R.failed(null,"未获取到视频ID");
		}
		if (null == req.getPlatformType()){
			return R.failed(null,"未获取到平台类型");
		}
		if (StringUtils.isBlank(req.getAdvertiserIds())){
			return R.failed(null,"未获取到广告账户");
		}

		Map<String,Object> result = new HashMap<>();
		String[] idsGroup = req.getIds().split(",");
		for (String vid : idsGroup) {
			AdVideo adVideo = this.getById(vid);
			if (null != adVideo){
				//广告账户列表
				String[] advertiserIds = req.getAdvertiserIds().split(",");
				if (null != advertiserIds && advertiserIds.length > 0){
					for (String advertiserId : advertiserIds) {
						//判断视频,是否已经同步到此广告账户,同步过直接成功
						AdVideoPlatform adVideoPlatform = adVideoPlatformService.getOne(Wrappers.<AdVideoPlatform>query().lambda()
								.eq(AdVideoPlatform::getVid,adVideo.getId())
								.eq(AdVideoPlatform::getAdvertiserId,advertiserId)
								.last("LIMIT 1"));
						if (Objects.nonNull(adVideoPlatform)){
							result.put("code",0);
							result.put("msg","视频已同步三方平台");
							result.put("platform",adVideoPlatform);
							continue;
						}
						if (req.getPlatformType() == 1){
							if (Double.parseDouble(adVideo.getDuration()) < 4){
								return R.failed(null,"视频时长小于4秒同步失败");
							}
							//上传头条
							result = uploadVideoTt(advertiserId,adVideo);
						}else if(req.getPlatformType() == 2){
							//上传广点通
							result = uploadVideoGdt(advertiserId,adVideo);
						}else{
							return R.failed(null,"无效的平台ID");
						}
						if(0 != (int)(result.get("code"))){
							log.info(result.get("msg"));
							return R.failed(null,String.valueOf(result.get("msg")));
						}
					}
				}else{
					log.error(">>>未获取到广告账户");
					return R.failed(null,"未获取到广告账户");
				}
			}else{
				log.error(">>>未获取到视频");
				return R.failed(null,"未获取到视频");
			}
		}
		log.info(">>>操作成功");
		return R.ok(result,"操作成功");
	}
	/**
	 * 视频上传头条
	 * @param advertiserId 广告账户
	 * @param adVideo 视频信息对象
	 * @return
	 */
	public Map<String,Object> uploadVideoTt(String advertiserId,AdVideo adVideo) {
		Map<String,Object> result = new HashMap<String,Object>();
		//获取token
		String accessToken =  ttAccesstokenService.fetchAccesstoken(advertiserId);
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("advertiser_id", advertiserId);
		params.put("md5",adVideo.getMd5());
		params.put("realPath",adVideo.getRealPath());
		params.put("filename",adVideo.getVName());
		//调第三方平台接口
		JSONObject resultStr = this.uploadAdvideo(openApiUrlToutiao,params,accessToken);
		ResponseBean resBean = JSON.parseObject(resultStr.toJSONString(), ResponseBean.class);
		//调用成功
		if(resBean != null && "0".equals(resBean.getCode())){
			Map<String,Object> videoData = resBean.getData();
			AdVideoPlatform adp = new AdVideoPlatform();
			adp.setType("1");//1头条
			adp.setVid(String.valueOf(adVideo.getId()));
			adp.setAdvertiserId(advertiserId);//广告账户
			adp.setPlatformVid(String.valueOf(videoData.get("video_id")));
			adp.setMaterialId(String.valueOf(videoData.get("material_id")));
			adp.setUpdatetime(new Date());

			AdVideoPlatform adVideoPlatform = adVideoPlatformService.getOne(Wrappers.<AdVideoPlatform>query().lambda().eq(AdVideoPlatform::getVid,adVideo.getId())
					.eq(AdVideoPlatform::getAdvertiserId,advertiserId).last("LIMIT 1"));
			if (null == adVideoPlatform){
				adVideoPlatformService.save(adp);
				result.put("platform",adp);
			}else{
				result.put("platform",adVideoPlatform);
			}
			log.info(">>>平台视频ID:{}，广告账户:{}，头条视频ID:{} >>>素材ID:{}，同步成功",adVideo.getId(),advertiserId,String.valueOf(videoData.get("video_id")),String.valueOf(videoData.get("material_id")));
		}else{
			if (Objects.isNull(resBean)){
				result.put("code",-1);
				result.put("msg","操作失败，未知错误");
				return result;
			}else {
				result.put("code",-1);
				result.put("msg",">>>视频ID："+adVideo.getId()+"，广告账户："+advertiserId+"，失败，原因："+resBean.getMessage());
				log.info(result.get("msg"));
				return result;
			}
		}
		result.put("code",0);
		result.put("msg","操作成功");
		return result;
	}
	/**
	 * 视频上传广点通
	 * @param advertiserId 广告账户
	 * @param adVideo 视频信息对象
	 * @return
	 */
	public Map<String,Object> uploadVideoGdt(String advertiserId,AdVideo adVideo) {
		Map<String,Object> result = new HashMap<String,Object>();
		//advertiserId = "17209785";
		//公共方法获取accessToken
		Map<String, String> map = gdtAccesstokenService.fetchAccesstoken(advertiserId);
		//定义广点通接口url
		String url = gdtUrl + gdtVideoAdd + "?" + MapUtils.queryString(map);
		// 文件参数
		FileBody file = new FileBody(new File(adVideo.getRealPath()));
		MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create()
				.addPart("video_file", file);
		// 其他参数
		entityBuilder.addTextBody("account_id", advertiserId);
		entityBuilder.addTextBody("signature", adVideo.getMd5());
		//调第三方平台（广点通）接口
		String resultStr = OEHttpUtils.doFilePost(url, entityBuilder);
		ResponseBean resBean = JSON.parseObject(resultStr, ResponseBean.class);
		//调用成功,信息入库
		if(resBean != null && "0".equals(resBean.getCode())){
			Map<String,Object> videoData = resBean.getData();
			AdVideoPlatform adp = new AdVideoPlatform();
			adp.setType("2");	//2广点通
			adp.setVid(String.valueOf(adVideo.getId()));
			adp.setAdvertiserId(advertiserId);//广告账户
			adp.setPlatformVid(String.valueOf(videoData.get("video_id")));
			adp.setMaterialId(String.valueOf(videoData.get("video_id")));
			adp.setUpdatetime(new Date());

			AdVideoPlatform adVideoPlatform = adVideoPlatformService.getOne(Wrappers.<AdVideoPlatform>query().lambda().eq(AdVideoPlatform::getVid,adVideo.getId())
					.eq(AdVideoPlatform::getAdvertiserId,advertiserId).last("LIMIT 1"));
			if (null == adVideoPlatform){
				adVideoPlatformService.save(adp);
				result.put("platform",adp);
			}else{
				result.put("platform",adVideoPlatform);
			}
			log.info(">>>平台视频ID:{}，广告账户:{}，广点通视频ID:{}，同步成功",adVideo.getId(),advertiserId,String.valueOf(videoData.get("video_id")));
		}else{
			if (Objects.isNull(resBean)){
				result.put("code",-1);
				result.put("msg","操作失败，未知错误");
				return result;
			}else {
				result.put("code", -1);
				result.put("msg", ">>>广点通视频ID：" + adVideo.getId() + "，广告账户：" + advertiserId + "，失败，原因：" + resBean.getMessage());
				log.info(result.get("msg"));
				return result;
			}
		}
		result.put("code",0);
		result.put("msg","操作成功");
		return result;
	}
	/**
	 * 查看视频报表信息
	 * @param param
	 * @return
	 */
	@Override
	public R findReport(Map<String,Object> param){
		List<AdVideoReport> resultList = Lists.newArrayList();
		List<AdVideoPlatform> adVpfList = adVideoPlatformService.list(Wrappers.<AdVideoPlatform>query().lambda().eq(AdVideoPlatform::getVid,param.get("vid")));
		if (adVpfList.size() > 0) {
			List<Long> mIdsList = new ArrayList<>();
			for (AdVideoPlatform adv : adVpfList) {
				mIdsList.add(Long.parseLong(adv.getMaterialId()));
			}
			param.put("material_ids",mIdsList);
			//获取当前账号下 广告账户列表
			List<String> advertiserList = advService.getOwnerAdv(SecurityUtils.getUser().getId(),null);
			if (advertiserList.size() > 0){
				List<Long> advList = new ArrayList<>();
				for (String adv : advertiserList) { //listString转listLong
					advList.add(Long.parseLong(adv));
				}
				param.put("advertiser_ids",advList);
				//头条视频报表
				resultList = adVideoReportMapper.selectTtVideoReport(param);
				if (null != resultList && resultList.size()>0){
					resultList.forEach(item->{
						item.setName("头条");
					});
				}
				//广点通视频报表
				List<AdVideoReport> gdtReportList = adVideoReportMapper.selectGdtVideoReport(param);
				if (gdtReportList.size() > 0){
					gdtReportList.forEach(item->{
						item.setName("广点通");
					});
					resultList.addAll(gdtReportList);
				}
			}else{
				R.failed(null,"未绑定广告账户，无法查看");
			}
		}
		return R.ok(resultList);
	}

	/**
	 * 调用头条接口上传视频
	 * @param url
	 * @param data
	 * @param token
	 * @return
	 */
	public JSONObject uploadAdvideo(String url, Map<String, Object> data, String token) {
		// 构造请求
		HttpPost httpPost = new HttpPost(url);
		httpPost.setHeader("Access-Token", token);

		// 文件参数
		FileBody file = new FileBody(new File(String.valueOf(data.get("realPath"))));
		MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create()
				.addPart("video_file", file);
		// 其他参数
		entityBuilder.addTextBody("advertiser_id", String.valueOf(data.get("advertiser_id")));
		entityBuilder.addTextBody("video_signature", String.valueOf(data.get("md5")));
		entityBuilder.addTextBody("filename",String.valueOf(data.get("filename")), ContentType.APPLICATION_JSON);
		HttpEntity entity = entityBuilder.build();


		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;

		try {
			client = HttpClientBuilder.create().build();
			httpPost.setURI(URI.create(url));

			httpPost.setEntity(entity);

			response = client.execute(httpPost);
			if (response != null && response.getStatusLine().getStatusCode() == 200) {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
				StringBuffer result = new StringBuffer();
				String line = "";
				while ((line = bufferedReader.readLine()) != null) {
					result.append(line);
				}
				bufferedReader.close();
				return JSONObject.parseObject(result.toString());
			}

		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				client.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	/**
	 * 获取视频已推送的广告账户
	 * @param req
	 * @return
	 */
	@Override
	public R getPushAdList(AdVideoPlatformVo req) {
		req.setUserId(SecurityUtils.getUser().getId());
		List<AdVideoPlatformVo> list = adVideoPlatformMapper.selectAdVideoPlatformByList(req);
		return R.ok(list);
	}

	/**
	 * 视频投放数据
	 * @param req
	 * @return
	 */
	@Override
	public R getAdVideoReport(AdVideoReportVo req){
		//当前用户绑定的广告账户
		List<String> adList = advService.getOwnerAdv(SecurityUtils.getUser().getId(), null);
		//查询分页数据
		req.setAdList(adList);
		req.setCreateUser(String.valueOf(SecurityUtils.getUser().getId()));
		IPage<AdVideoReportData> page = mapper.selectAdVideoReportList(req);
		List<AdVideoReportData> list = Lists.newArrayList();
		try {
			if (Objects.nonNull(page)){
				Map<String, Object> paramMap = new HashMap<>();
				paramMap.put("startTime", Long.parseLong(req.getSTime().replace("-", "")));
				paramMap.put("endTime", Long.parseLong(req.getETime().replace("-", "")));
				paramMap.put("adList", req.getAdList());

				for (AdVideoReportData adVideo:page.getRecords()) {
					String id = adVideo.getId();
					paramMap.put("id", id);

					if (Objects.isNull(req.getPlatformId()) || Integer.parseInt(PlatformTypeEnum.TT.getValue())==req.getPlatformId()) {
						//头条>获取运营数据
						AdVideoReportData data = getTtAdOperateData(adVideo,paramMap);
						list.add(data);
					}

					if (Objects.isNull(req.getPlatformId()) || Integer.parseInt(PlatformTypeEnum.GDT.getValue())==req.getPlatformId()) {
						//广点通>获取运营数据
						AdVideoReportData data = getGdtAdOperateData(adVideo,paramMap);
						list.add(data);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		page.setRecords(list);
		return R.ok(page);
	}


	/**
	 * 视频投放数据（使用presto）
	 * @param req
	 * @return
	 */
	@Override
	public R getPrestoAdVideoReport(AdVideoReportVo req){
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("startTime", Long.parseLong(req.getSTime().replace("-", "")));
		paramMap.put("endTime", Long.parseLong(req.getETime().replace("-", "")));
		Integer platformId = req.getPlatformId();
		if(platformId != null){
			paramMap.put("platformId", platformId);
		}
		Integer makeId = req.getMakeId();
		if(makeId != null){
			paramMap.put("makeId", makeId);
		}
		String videoName = req.getVideoName();
		if(StringUtils.isNotBlank(videoName)){
			paramMap.put("videoName", videoName);
		}
		String labelname = req.getLabelname();
		if(StringUtils.isNotBlank(labelname)){
			paramMap.put("labelname", labelname);
		}

		//由于预加载，会导致项目中变量赋值进去
		/*Integer id = req.getId();
		if(id != null){
			paramMap.put("id", id);
		}*/

		//增加presto动态schema--对应不同的库
		paramMap.put("pigSchema", pigSchema);
		paramMap.put("ch3399Schema", ch3399Schema);

		List<AdVideoAdsReportDTO> list = new ArrayList<>();//adVideoAdsReportMapper.selectAdVideoAdsReport(paramMap);
		if(CollectionUtils.isNotEmpty(list)){
			R<List<SysUser>> data = remoteUserService.getUserList(SecurityConstants.FROM_IN);
			if(data.getCode() == 0) {
				List<SysUser> ulist = data.getData();
				Map<String, String> userMap = ulist.stream().collect(HashMap::new, (m, v) -> m.put(String.valueOf(v.getUserId()), v.getRealName()), HashMap::putAll);
				for(AdVideoAdsReportDTO entity : list){
					String createuser = entity.getCreateuser();
					if(StringUtils.isNotBlank(createuser)){
						String realname = userMap.get(createuser);
						entity.setMakeName(realname);
					}
				}
			}
		}


		return R.ok(list);
	}

	private long offset(long current, long size) {
		if (current <= 1L) {
			return 1L;
		}
		return (current - 1) * size + 1L;
	}


	/**
	 * 头条>获取运营数据
	 * @param adVideo
	 * @param paramMap
	 * @return
	 */
	public AdVideoReportData getTtAdOperateData(AdVideoReportData adVideo,Map<String, Object> paramMap){
		AdVideoReportData data = new AdVideoReportData();
		data.setId(adVideo.getId());
		data.setVideoName(adVideo.getVideoName());
		data.setVideoUrl(adVideo.getVideoUrl());
		data.setVideoImageUrl(adVideo.getVideoImageUrl());
		data.setMakeName(adVideo.getMakeName());
		data.setPlatformName("头条");

		AdVideoPlatform adVpfList = adVideoPlatformService.getOne(Wrappers.<AdVideoPlatform>query().lambda().eq(AdVideoPlatform::getVid, adVideo.getId())
						.eq(AdVideoPlatform::getType, PlatformTypeEnum.TT.getValue()).last("LIMIT 1"));

		if (Objects.nonNull(adVpfList)) {
			paramMap.put("materialId", Long.parseLong(adVpfList.getMaterialId()));
			//查询视频头条报表数据
			AdVideoReportData ttVideoData = adVideoReportMapper.selectTtVideoReportData(paramMap);
			if (Objects.nonNull(ttVideoData) && ttVideoData.getShowData() > 0) {
				//消耗
				data.setCost(ttVideoData.getCost());
				//展示数
				data.setShowData(ttVideoData.getShowData());
				//点击数
				data.setClick(ttVideoData.getClick());
				//25%播放占比
				data.setPlay25FeedBreakRate(ttVideoData.getPlay25FeedBreakRate());
				//50%播放占比
				data.setPlay50FeedBreakRate(ttVideoData.getPlay50FeedBreakRate());
				//99%播放占比
				data.setPlay99FeedBreakRate(ttVideoData.getPlay99FeedBreakRate());
			}
		}
		if (Objects.nonNull(data.getShowData())) {
			//查询此视频在那些广告计划使用
			List<AdCreative> adCreatives = advCreativeService.list(Wrappers.<AdCreative>query().lambda().eq(AdCreative::getVideoId, adVpfList.getPlatformVid()));
			if (Objects.nonNull(adCreatives)) {
				List<String> adIdList = Lists.newArrayList();
				for (AdCreative adCreative : adCreatives) {
					adIdList.add(String.valueOf(adCreative.getAdId()));
				}
				paramMap.put("adIdList", adIdList);
				//统计运营平台数据
				AdVideoOperateData adVideoOperateData = adVideoOperateReportMapper.selectAdVideoOperateData(paramMap);
				//处理数据
				dealOperateData(data, adVideoOperateData);
			}
		}
		return data;
	}
	/**
	 * 广点通>获取运营数据
	 * @param adVideo
	 * @param paramMap
	 * @return
	 */
	public AdVideoReportData getGdtAdOperateData(AdVideoReportData adVideo,Map<String, Object> paramMap){
		AdVideoReportData data = new AdVideoReportData();
		data.setId(adVideo.getId());
		data.setVideoName(adVideo.getVideoName());
		data.setVideoUrl(adVideo.getVideoUrl());
		data.setVideoImageUrl(adVideo.getVideoImageUrl());
		data.setMakeName(adVideo.getMakeName());
		data.setPlatformName("广点通");

		AdVideoPlatform gdtAdVpfList = adVideoPlatformService.getOne(Wrappers.<AdVideoPlatform>query().lambda().eq(AdVideoPlatform::getVid, adVideo.getId())
				.eq(AdVideoPlatform::getType, PlatformTypeEnum.GDT.getValue()).last("LIMIT 1"));

		if (Objects.nonNull(gdtAdVpfList)) {
			paramMap.put("materialId", Long.parseLong(gdtAdVpfList.getMaterialId()));
			//查询视频头条报表数据
			AdVideoReportData gdtVideoData = adVideoReportMapper.selectGdtVideoReportData(paramMap);
			if (Objects.nonNull(gdtVideoData) && gdtVideoData.getShowData() > 0) {
				//消耗
				data.setCost(gdtVideoData.getCost());
				//展示数
				data.setShowData(gdtVideoData.getShowData());
				//点击数
				data.setClick(gdtVideoData.getClick());
				//25%播放占比
				data.setPlay25FeedBreakRate(gdtVideoData.getPlay25FeedBreakRate());
				//50%播放占比
				data.setPlay50FeedBreakRate(gdtVideoData.getPlay50FeedBreakRate());
				//99%播放占比
				data.setPlay99FeedBreakRate(gdtVideoData.getPlay99FeedBreakRate());
			}
		}
		if (Objects.nonNull(data.getShowData())) {
			//查询此视频在那些广告计划使用
			List<String> adCreatives = adVideoReportMapper.selectGdtAdCreativeByList(paramMap);
			if (Objects.nonNull(adCreatives)) {
				paramMap.put("adIdList", adCreatives);
				//统计运营平台数据
				AdVideoOperateData adVideoOperateData = adVideoOperateReportMapper.selectAdVideoOperateData(paramMap);
				//处理数据
				dealOperateData(data, adVideoOperateData);
			}
		}
		return data;
	}
	/**
	 * 处理视频投放统计数据
	 * @param data
	 * @param adVideoOperateData
	 */
	public void dealOperateData(AdVideoReportData data,AdVideoOperateData adVideoOperateData){
		//消耗
		BigDecimal cost = data.getCost();
		//激活数
		String active = adVideoOperateData.getActive();
		//注册数
		String register = adVideoOperateData.getRegister();
		//新增付费人数
		String newPayUserNumber = adVideoOperateData.getNewPayUserNumber();
		//新增付费金额
		String newPayMoney = adVideoOperateData.getNewPayMoney();
		//总付费金额
		String payMoney = adVideoOperateData.getPayMoney();
		//付费次数
		String payNumber = adVideoOperateData.getPayNumber();
		//首日充值金额
		String worth0 = adVideoOperateData.getWorth0();

		//总付费金额
		data.setPayMoney(new BigDecimal(payMoney).setScale(2, BigDecimal.ROUND_HALF_UP));
		if (StringUtils.isNotBlank(active) && Integer.parseInt(active) > 0){
			data.setActive(Integer.parseInt(active));
			if (Objects.nonNull(cost)) {
				//激活成本
				data.setActiveCost(cost.divide(new BigDecimal(active),2, BigDecimal.ROUND_HALF_UP));
			}
			if (Objects.nonNull(register)) {
				//注册率
				data.setRegisterRate(new BigDecimal(register).divide(new BigDecimal(active),4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
			}
			if (Objects.nonNull(newPayUserNumber)) {
				//新增付费率
				data.setNewPayRate(new BigDecimal(newPayUserNumber).divide(new BigDecimal(active),4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
			}
			if (Objects.nonNull(worth0)) {
				//首日LTV
				data.setFirstDayLTV(new BigDecimal(worth0).divide(new BigDecimal(active),2, BigDecimal.ROUND_HALF_UP));
			}
			if (Objects.nonNull(adVideoOperateData.getWorth3())) {
				//3日LTV
				data.setThreeDayLTV(new BigDecimal(adVideoOperateData.getWorth3()).divide(new BigDecimal(active),2, BigDecimal.ROUND_HALF_UP));
			}
			if (Objects.nonNull(adVideoOperateData.getWorth7())) {
				//7日LTV
				data.setSevenDayLTV(new BigDecimal(adVideoOperateData.getWorth7()).divide(new BigDecimal(active),2, BigDecimal.ROUND_HALF_UP));
			}
			if (Objects.nonNull(adVideoOperateData.getWorth15())) {
				//15日LTV
				data.setFifteenDayLTV(new BigDecimal(adVideoOperateData.getWorth15()).divide(new BigDecimal(active),2, BigDecimal.ROUND_HALF_UP));
			}
			if (Objects.nonNull(adVideoOperateData.getWorth30())) {
				//30日LTV
				data.setThirtyDayLTV(new BigDecimal(adVideoOperateData.getWorth30()).divide(new BigDecimal(active),2, BigDecimal.ROUND_HALF_UP));
			}
		}
		//点击数
		Integer click = data.getClick();
		if (Objects.nonNull(click) && click > 0){
			if (Objects.nonNull(active)) {
				//点击激活率
				data.setClickActiveRate(new BigDecimal(active).divide(new BigDecimal(click),4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
			}
		}

		if (StringUtils.isNotBlank(register) && Integer.parseInt(register) > 0){
			data.setRegister(Integer.parseInt(register));
			if (Objects.nonNull(register)) {
				//注册成本
				data.setRegisterCost(cost.divide(new BigDecimal(register),2, BigDecimal.ROUND_HALF_UP));
			}
		}

		if (StringUtils.isNotBlank(newPayUserNumber) && Integer.parseInt(newPayUserNumber) > 0){
			data.setNewPayUserNumber(Integer.parseInt(newPayUserNumber));
			if (Objects.nonNull(newPayUserNumber)) {
				//新增付费成本
				data.setNewPayCost(cost.divide(new BigDecimal(newPayUserNumber),2, BigDecimal.ROUND_HALF_UP));
			}
		}

		if(Objects.nonNull(cost) && cost.compareTo(new BigDecimal(0)) > 0){
			if (Objects.nonNull(worth0)) {
				//首日ROI
				data.setFirstDayROI(new BigDecimal(worth0).divide(cost,4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
			}
			if (Objects.nonNull(payMoney)) {
				//累计ROI
				data.setTotalROI(new BigDecimal(payMoney).divide(cost,4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
			}
		}
		if (StringUtils.isNotBlank(newPayMoney)) {
			data.setNewPayMoney(new BigDecimal(newPayMoney));
		}
		String num2 = adVideoOperateData.getNum2();
		String sumnum2 = adVideoOperateData.getSumnum2();
		if (Objects.nonNull(sumnum2) && Integer.parseInt(sumnum2) > 0){
			if (Objects.nonNull(num2)) {
				//次留
				data.setTwoStayRate(new BigDecimal(num2).divide(new BigDecimal(sumnum2),4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
			}
		}
		String num3 = adVideoOperateData.getNum3();
		String sumnum3 = adVideoOperateData.getSumnum3();
		if (Objects.nonNull(sumnum3) && Integer.parseInt(sumnum3) > 0){
			if (Objects.nonNull(num3)) {
				//3日留
				data.setThreeStayRate(new BigDecimal(num3).divide(new BigDecimal(sumnum3),4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
			}
		}
		String num7 = adVideoOperateData.getNum7();
		String sumnum7 = adVideoOperateData.getSumnum7();
		if (Objects.nonNull(sumnum7) && Integer.parseInt(sumnum7) > 0){
			if (Objects.nonNull(num7)) {
				//7日留
				data.setSevenStayRate(new BigDecimal(num7).divide(new BigDecimal(sumnum7),4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
			}
		}

		String num15 = adVideoOperateData.getNum15();
		String sumnum15 = adVideoOperateData.getSumnum15();
		if (Objects.nonNull(sumnum15) && Integer.parseInt(sumnum15) > 0){
			if (Objects.nonNull(num15)) {
				//15日留
				data.setFifteenStayRate(new BigDecimal(num15).divide(new BigDecimal(sumnum15),4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
			}
		}

		String num30 = adVideoOperateData.getNum30();
		String sumnum30 = adVideoOperateData.getSumnum30();
		if (Objects.nonNull(sumnum30) && Integer.parseInt(sumnum30) > 0){
			if (Objects.nonNull(num30)) {
				//30日留
				data.setThirtyStayRate(new BigDecimal(num30).divide(new BigDecimal(sumnum30),4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
			}
		}



		if (StringUtils.isNotBlank(payNumber)){
			//付费次数
			data.setPayNumber(Integer.parseInt(payNumber));
		}
		if (Objects.nonNull(data.getClick()) && Objects.nonNull(data.getShowData()) && data.getShowData() > 0){
			//点击率
			data.setCtr(new BigDecimal(data.getClick()).divide(new BigDecimal(data.getShowData()),4,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
		}

	}

}
